//!
/**
 ***********************************************************************************************************
 * <RBDefaultGeometrySorter Implementation>
 ***********************************************************************************************************
 * @file RBDefaultGeometrySorter.cpp
 ***********************************************************************************************************/

/***********************************************************************************************************
 * Precompiled Header
 ***********************************************************************************************************/
#include "RBMainPCH.h"

/***********************************************************************************************************
 * Includes
 ***********************************************************************************************************/
#include "RBDefaultGeometrySorter.h"
#include "RBCamera.h"
#include "RBGeometry.h"

/***********************************************************************************************************
 * Defines
 ***********************************************************************************************************/

/***********************************************************************************************************
 * Classes implementation
 ***********************************************************************************************************/


/***********************************************************************************************************
 *
 ***********************************************************************************************************/
RBDefaultGeometrySorter::RBDefaultGeometrySorter(RBCamera* camera)
: m_camera(camera)
{

}

/***********************************************************************************************************
 *
 ***********************************************************************************************************/
RBDefaultGeometrySorter::~RBDefaultGeometrySorter()
{

}

/***********************************************************************************************************
 *
 ***********************************************************************************************************/
bool RBDefaultGeometrySorter::operator()(RBGeometryHandle lhs, RBGeometryHandle rhs) const
{
    RBGeometry* pLhs = &RBGeometry::Get(lhs);
    RBGeometry* pRhs = &RBGeometry::Get(rhs);
    if (pLhs->Priority == pRhs->Priority)
    {
        RBMaterial* pMaterial1 = pLhs->GetMaterial();
        RBMaterial* pMaterial2 = pRhs->GetMaterial();
        if (!pMaterial1->BlendState.IsAlphaBlended && !pMaterial2->BlendState.IsAlphaBlended)
        {
            // Both material are opaque: sort by material ID
            return pMaterial1->BlendState.Mask < pMaterial2->BlendState.Mask;
        }
        else if (pMaterial1->BlendState.IsAlphaBlended)
        {
            return false;
        }
        else if (pMaterial2->BlendState.IsAlphaBlended)
        {
            return true;
        }
        else
        {
            // Sort by depth wrt the camera
            float3 vCameraBack;
            m_camera->WorldXForm().Rotate.GetCol(2, vCameraBack);
            // Do it only on position and not on the position - camerapos 
            // because of the linearity of the dot product
            float fDist1 = -vCameraBack.Dot(pLhs->WorldXForm().Translate);
            float fDist2 = -vCameraBack.Dot(pRhs->WorldXForm().Translate);

            // Sort back to front
            return fDist1 > fDist2;
        }
    }
    else
    {
        return pLhs->Priority < pRhs->Priority;
    }

}
